package com.lily.agent;

import org.objectweb.asm.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class ClassInfoCollector extends ClassVisitor {
    private final Map<String, Object> classInfo = new HashMap<>();
    private final List<Map<String, Object>> fields = new ArrayList<>();
    private final List<Map<String, Object>> methods = new ArrayList<>();

    public ClassInfoCollector() {
        super(Opcodes.ASM9);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        classInfo.put("className", name.replace('/', '.'));
        super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        Map<String, Object> fieldInfo = new HashMap<>();
        fieldInfo.put("name", name);
        fieldInfo.put("descriptor", descriptor);
        fields.add(fieldInfo);
        return super.visitField(access, name, descriptor, signature, value);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        Map<String, Object> methodInfo = new HashMap<>();
        methodInfo.put("name", name);
        methodInfo.put("descriptor", descriptor);
        Type returnType = Type.getReturnType(descriptor);
        methodInfo.put("returnType", returnType.getClassName());
        Type[] argumentTypes = Type.getArgumentTypes(descriptor);
        List<String> parameterTypes = new ArrayList<>();
        for (Type argType : argumentTypes) {
            parameterTypes.add(argType.getClassName());
        }
        methodInfo.put("parameterTypes", parameterTypes);
        methods.add(methodInfo);
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }

    @Override
    public void visitEnd() {
        classInfo.put("fields", fields);
        classInfo.put("methods", methods);
        super.visitEnd();
    }

    public Map<String, Object> getClassInfo() {
        return classInfo;
    }
}